﻿//------------------------------------------------------------------------------
// <copyright file="Locate.cs" company="Company">
//     Copyright (c) Company.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

using System;
using System.ComponentModel.Design;
using System.Globalization;
using System.Collections;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System.Collections.Generic;
using Microsoft.VisualStudio;
using EnvDTE;
using Microsoft.VisualStudio.CommandBars;
using EnvDTE80;

namespace OnePieceAssist
{
    /// <summary>
    /// Command handler
    /// </summary>
    internal sealed class Locate
    {
        /// <summary>
        /// Command ID.
        /// </summary>
        public const int CommandId = 0x0100;

        /// <summary>
        /// Command menu group (command set GUID).
        /// </summary>
        public static readonly Guid CommandSet = new Guid("67c78c65-4807-4971-87e0-7453f5f24d66");

        /// <summary>
        /// VS Package that provides this command, not null.
        /// </summary>
        private readonly Package package;

        /// <summary>
        /// Initializes a new instance of the <see cref="Locate"/> class.
        /// Adds our command handlers for menu (commands must exist in the command table file)
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        private Locate(Package package)
        {
            if (package == null)
            {
                throw new ArgumentNullException("package");
            }

            this.package = package;
            OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
            if (commandService != null)
            {
                var menuCommandID = new CommandID(CommandSet, CommandId);
                var menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID);
                commandService.AddCommand(menuItem);                           
            }
        }

        /// <summary>
        /// Gets the instance of the command.
        /// </summary>
        public static Locate Instance
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the service provider from the owner package.
        /// </summary>
        private IServiceProvider ServiceProvider
        {
            get
            {
                return this.package;
            }
        }

        /// <summary>
        /// Initializes the singleton instance of the command.
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        public static void Initialize(Package package)
        {
            Instance = new Locate(package);
        }
        /// <summary>
        /// This function is the callback used to execute the command when the menu item is clicked.
        /// See the constructor to see how the menu item is associated with this function using
        /// OleMenuCommandService service and MenuCommand class.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event args.</param>
        private void MenuItemCallback(object sender, EventArgs e)
        {
            DTE2 dte = this.ServiceProvider.GetService(typeof(DTE)) as DTE2;

            System.Array projs = (System.Array)dte.ActiveSolutionProjects;
            if (projs.Length > 0)
            {
                Project pro = (Project)projs.GetValue(0);
                ConfigurationManager mng = pro.ConfigurationManager;
                Configuration config = mng.ActiveConfiguration;
                //                 Properties pers = config.Properties;
                //                 foreach (Property per in pers)
                //                 {
                //                     System.Diagnostics.Trace.WriteLine(per.Name + "  " + per.Value);
                //                 }
                OutputGroups groups = config.OutputGroups;
                foreach (OutputGroup group in groups)
                {
                    object obj = group.FileNames;
                    System.Array urls = (System.Array)group.FileURLs;
                    if (group.CanonicalName == "Built" && urls.Length > 0)
                    {
                        System.Diagnostics.Trace.WriteLine(group.CanonicalName + "  " + group.DisplayName + "  " + group.Description);

                        string url = (string)urls.GetValue(0);
                        string preStr = "file:///";
                        if (url.StartsWith(preStr))
                        {
                            url = url.Remove(0, preStr.Length);
                            url = url.Replace("\\\\", "\\");
                            System.Diagnostics.Trace.WriteLine(url);

                            System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo("Explorer.exe");
                            if (System.IO.File.Exists(url))
                            {
                                psi.Arguments = "/e,/select," + url;
                            }
                            else
                            {
                                char[] _any = { '\\', '/' };
                                int lastIdx = url.LastIndexOfAny(_any);
                                if (lastIdx != -1)
                                {
                                    url = url.Remove(lastIdx, url.Length - lastIdx);
                                }

                                psi.Arguments = "/e," + url;
                            }
                            System.Diagnostics.Process.Start(psi);
                        }
                    }
                }
            }            
        }

        public static IEnumerable<EnvDTE.Project> GetProjects(IVsSolution solution)
        {
            foreach (IVsHierarchy hier in GetProjectsInSolution(solution))
            {
                EnvDTE.Project project = GetDTEProject(hier);
                if (project != null)
                    yield return project;
            }
        }

        public static IEnumerable<IVsHierarchy> GetProjectsInSolution(IVsSolution solution)
        {
            return GetProjectsInSolution(solution, __VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION);
        }

        public static IEnumerable<IVsHierarchy> GetProjectsInSolution(IVsSolution solution, __VSENUMPROJFLAGS flags)
        {
            if (solution == null)
                yield break;

            IEnumHierarchies enumHierarchies;
            Guid guid = Guid.Empty;
            solution.GetProjectEnum((uint)flags, ref guid, out enumHierarchies);
            if (enumHierarchies == null)
                yield break;

            IVsHierarchy[] hierarchy = new IVsHierarchy[1];
            uint fetched;
            while (enumHierarchies.Next(1, hierarchy, out fetched) == VSConstants.S_OK && fetched == 1)
            {
                if (hierarchy.Length > 0 && hierarchy[0] != null)
                    yield return hierarchy[0];
            }
        }

        public static EnvDTE.Project GetDTEProject(IVsHierarchy hierarchy)
        {
            if (hierarchy == null)
                throw new ArgumentNullException("hierarchy");

            object obj;
            hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ExtObject, out obj);
            return obj as EnvDTE.Project;
        }
    }
}
